package de.jmda.mview.fx.node.typeshape;

import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.geometry.Bounds;
import javafx.geometry.Point2D;
import javafx.scene.Node;
import javafx.scene.control.Label;
import javafx.scene.image.ImageView;

import javax.lang.model.element.Element;

import org.apache.log4j.Logger;

import de.jmda.fx.node.Util;
import de.jmda.mview.typeshape.DisplayOptionsModelUtil;

/**
 * @author rwegner
 */
public class FieldView extends ElementView
{
	private final static Logger LOGGER = Logger.getLogger(FieldView.class);

	private Typeshape typeshape;
	
	private ObjectProperty<Point2D> anchorLeft;
	public Point2D getAnchorLeft() { return anchorLeft.get(); }
	protected void setAnchorLeft(Point2D anchor) { anchorLeft.set(anchor); }
	public ObjectProperty<Point2D> anchorLeftProperty() { return anchorLeft; }

	private ObjectProperty<Point2D> anchorRight;
	public Point2D getAnchorRight() { return anchorRight.get(); }
	protected void setAnchorRight(Point2D anchor) { anchorRight.set(anchor); }
	public ObjectProperty<Point2D> anchorRightProperty() { return anchorRight; }
	
	public FieldView(
			ElementData<? extends Element> elementData,
			DisplayOptionsModelUtil displayOptionsModelUtil,
			Typeshape typeshape)
  {
	  super(elementData, displayOptionsModelUtil);

	  this.typeshape = typeshape;

	  anchorLeft  = new SimpleObjectProperty<Point2D>();
	  anchorRight = new SimpleObjectProperty<Point2D>();

		icon = new ImageView(elementData.getImage());
		type = new Label(elementData.getType());
		name = new Label(elementData.getName());
		
		ChangeListenerBounds<Bounds> iconChangeListenerBounds =
				new ChangeListenerBounds<Bounds>(icon);
//		ChangeListenerBounds<Bounds> typeChangeListenerBounds =
//				new ChangeListenerBounds<Bounds>(type);
		ChangeListenerBounds<Bounds> nameChangeListenerBounds =
				new ChangeListenerBounds<Bounds>(name);
		
		icon.boundsInParentProperty().addListener(iconChangeListenerBounds);
//		type.boundsInParentProperty().addListener(typeChangeListenerBounds);
		name.boundsInParentProperty().addListener(nameChangeListenerBounds);

		typeshape.boundsInParentProperty().addListener
		(
				new ChangeListener<Bounds>()
				{
					public void changed(
							ObservableValue<? extends Bounds> source,
					    Bounds oldValue, Bounds newValue)
					{
						Point2D pos2DInParent =
								Util.pos2DInParent(icon, FieldView.this.typeshape.getParent());

						anchorLeft.set(
								new Point2D(
										pos2DInParent.getX(),
										pos2DInParent.getY() +
												(icon.getBoundsInParent().getHeight() / 2)));
						
						anchorRight.set(getAnchorRightOnTypeshape());
					}
//					public void changed(
//							ObservableValue<? extends Bounds> source,
//					    Bounds oldValue, Bounds newValue)
//					{
//						double x = 0;
//						double y = 0;
//		
//						Node nextNode;
//						Bounds bounds;
//
//						// calculate anchorPointLeft at icon
//						nextNode = icon;
//		
//						while ((nextNode != FieldView.this.typeshape.getParent()) &&
//						       (nextNode != null))
//						{
//							Bounds nextBounds = nextNode.getBoundsInParent();
//							x += nextBounds.getMinX();
//							y += nextBounds.getMinY();
//							nextNode = nextNode.getParent();
//						}
//		
//						bounds = icon.getBoundsInParent();
//
//						anchorLeft.set(new Point2D(x, y + bounds.getHeight() / 2));
//						
////						LOGGER.debug("x: " + x + " y: " + y + " xyPosOnScreen: " + Util.xyPosOnScene(icon));
//
//						// calculate anchorPointRight at name
//						x = 0;
//						y = 0;
//
//						nextNode = name;
//		
//						while ((nextNode != FieldView.this.typeshape.getParent()) &&
//						       (nextNode != null))
//						{
//							Bounds nextBounds = nextNode.getBoundsInParent();
//
//							x += nextBounds.getMinX();
//							y += nextBounds.getMinY();
//
//							nextNode = nextNode.getParent();
//						}
//		
//						bounds = name.getBoundsInParent();
//
//						anchorRight.set(
//								new Point2D(x + bounds.getWidth(), y + bounds.getHeight() / 2));
////						anchorRight.set(getAnchorRightOnTypeshape());
//
//						LOGGER.debug(
//								"anchorLeft " + anchorLeft.get() + " " +
//								"anchorRight " + anchorRight.get());
//					}
				}
		);
  }

	public Typeshape getTypeshape() { return typeshape; }
	
	/**
	 * @return calculated right anchor point <b>not</b> on right bound of {@link
	 *         ElementView#name} but on right bound of {@link #typeshape}.
	 */
	public Point2D getAnchorRightOnTypeshape()
	{
		Point2D result =
				new Point2D(
						// somehow x is a bit too big
						typeshape.getBoundsInParent().getMaxX() - 4,
						Util.pos2DInParent(name, typeshape.getParent()).getY() +
								(name.getBoundsInParent().getHeight() / 2));

		return result;
	}

	private class ChangeListenerBounds<T extends Bounds>
			implements ChangeListener<Bounds>
	{
		private Node node;
		
		public ChangeListenerBounds(Node node)
		{
			this.node = node;
		}

		@Override
    public void changed(
    		ObservableValue<? extends Bounds> observable,
        Bounds oldValue, Bounds newValue)
    {
			if (node == icon)
			{
				Point2D pos2DInParent = Util.pos2DInParent(node, typeshape.getParent());

				anchorLeft.set(
						new Point2D(
								pos2DInParent.getX(),
								pos2DInParent.getY() +
										(icon.getBoundsInParent().getHeight() / 2)));
			}
			else if (node == type)
			{
				// do nothing
			}
			else
			{
				anchorRight.set(getAnchorRightOnTypeshape());
			}

//			String nodename;
//			
//			if (node == icon)
//			{
//				nodename = "icon";
//			}
//			else if (node == type)
//			{
//				nodename = "type";
//			}
//			else
//			{
//				nodename = "name";
//			}
//
//			LOGGER.debug
//			(
//					String.format
//					(
////						"%1$9s %2$4s %3$20s %4$s", // parameter 1 mit 9 Stellen als String ...
//						"%1$9s %2$4s %3$20s anchorLeft %4$s anchorRight %4$s", // parameter 1 mit 9 Stellen als String ...
//						node.getClass().getSimpleName(),
//						nodename,
//						Util.pos2DInParent(node, typeshape.getParent()),
//						anchorLeft.get(),
//						anchorRight.get()
//					)
//			);
    }
	}
}